//Nguyen Trung Hieu
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import java.util.Vector;
import java.util.Calendar;
import java.text.SimpleDateFormat;

public class TaskHandling {
	
	enum COMMAND_TYPE {add, edit, delete, mark, mulmark, muldel} 	
	private UndoableEditListener listener;
	@SuppressWarnings("unused")
	private String fileName;
	private Storage currentStorage;
	
	public TaskHandling(String fileName){
		this.fileName = fileName;
		this.currentStorage = new Storage(fileName);
	}
	
	public static final String ID_FORMAT_FROM_TIME = "ddMMyyyyHHmmss";

	public static String generateTaskID() {
		Calendar cal = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat(ID_FORMAT_FROM_TIME);
		return sdf.format(cal.getTime());
	}
	
	public void addTask (Task task, int position, boolean undoAction){
		currentStorage.add(task, position);
		if (!undoAction){
			listener.undoableEditHappened(new UndoableEditEvent(this, new UndoableToggleEdit(COMMAND_TYPE.add, task, this, -1, "", "", "", "", "", "", null, null, null, null)));
		}
		currentStorage.updateFile();
	}
	
	public void add(String description,String date, String time, boolean undoAction){
		String TaskID = generateTaskID();
		/*System.out.println("desc = " + description);
		System.out.println("date = " + date);
		System.out.println("time = " + time);
		System.out.println("TaskID = " + TaskID);*/
		Task newTask = new Task(description,date, time, TaskID);
		if (!undoAction){
			listener.undoableEditHappened(new UndoableEditEvent(this, new UndoableToggleEdit(COMMAND_TYPE.add, newTask, this, -1, "", "", "", "", "", "", null, null, null, null)));
		}
		//System.out.println("add");
		currentStorage.add(newTask, -1);
		currentStorage.updateFile();
	}
	
	
	
	public Task deleteAndReturnTask(String taskID, boolean undoAction){
		System.out.println(currentStorage.retrieveTask(taskID));
		Task deleteTask = currentStorage.retrieveTask(taskID);
		int deleteTaskIndex = currentStorage.deleteTask(taskID);
		deleteTask.setOldPosition(deleteTaskIndex);
			if (!undoAction){
				listener.undoableEditHappened(new UndoableEditEvent(this, new UndoableToggleEdit(COMMAND_TYPE.delete, deleteTask, this, deleteTaskIndex, "", "", "", "", "", "", null, null, null, null)));
			}
		//System.out.println("deleteAndReturnTask");
		currentStorage.updateFile();
		return deleteTask;
	}
	
	public Task retriveTask(String taskID){
		return currentStorage.retrieveTask(taskID);
	}
	
	public Vector<Task> search(String searchKeyWord){
		return currentStorage.search(searchKeyWord);
	}
	

	public void updateFile(){
		currentStorage.updateFile();
	}
	
	public Vector<Task> getData(){
		return currentStorage.retrieveData();
	}
	
	//Set the undoableEditListenner
	public void addUndoableEditListener(UndoableEditListener l){
		this.listener = l;
	}

	//Remove the UndoableEditListener
	public void removeUndoableEditListener (UndoableEditListener l){
		this.listener = null;
	}
	
	public static Task createTask(String desc, String date, String time, String ID){
		Task createdTask = new Task (desc, date, time, ID);
		return createdTask;
	}
	
	public int searchByTaskID (String TaskID){
		return currentStorage.searchByTaskID(TaskID);
	}
	
	public void editTask (String newDesc,  String newTime, String newDate, String taskID, boolean undoAction){
		try {
		Task beingConsideredTask = currentStorage.retrieveTask(taskID);
		String oldDesc = beingConsideredTask.getDescription();
		String oldTime = beingConsideredTask.getTime();
		String oldDate = beingConsideredTask.getDate();
		currentStorage.retrieveTask(taskID).setDate(newDate);
		currentStorage.retrieveTask(taskID).setDescription(newDesc);
		currentStorage.retrieveTask(taskID).setTime(newTime);
		if (!undoAction){
			listener.undoableEditHappened(new UndoableEditEvent(this, new UndoableToggleEdit(COMMAND_TYPE.edit, currentStorage.retrieveTask(taskID), this, -1,  newDesc, newTime, newDate, oldDesc, oldTime, oldDate, null, null, null, null)));
		}} catch (NullPointerException nPE){
			System.out.println("OverdueTask Encountered!");
		}
	}
	
	
	public Task markAsDone(String taskID, TaskHandling destinationTaskHandling, int position, boolean undoAction){
		Task deletedTask = deleteAndReturnTask(taskID, true);
		destinationTaskHandling.addTask(deletedTask, position, true);				
		if (!undoAction){
			listener.undoableEditHappened(new UndoableEditEvent(this, new UndoableToggleEdit (COMMAND_TYPE.mark, deletedTask, this, -1, "", "", "", "", "", "", destinationTaskHandling, null, null, null)));
		}
		return deletedTask;
	}
	
	public void multipleMarkAsDone (String[] taskIDArr, TaskHandling destinationTaskHandling, boolean undoAction){
		Vector<Integer> taskPositions = new Vector<Integer>();
		for (int i = 0; i < taskIDArr.length; i++) {
			Task tempTask = markAsDone(taskIDArr[i],destinationTaskHandling, -1, true);
			taskPositions.add(tempTask.getOldPosition());
		}
		if (!undoAction){
			listener.undoableEditHappened(new UndoableEditEvent(this, new UndoableToggleEdit (COMMAND_TYPE.mulmark, null, this, -1, "", "", "", "", "", "", destinationTaskHandling, taskIDArr, null, taskPositions)));		
		}
	}

	public void multipleDelete (String[] taskIDArr, boolean undoAction){
		Vector<Task> deletedTasks = new Vector<Task>();
		Vector<Integer> taskPositions = new Vector<Integer>();
		for (int i = 0; i < taskIDArr.length; i++){
			Task tempTask = deleteAndReturnTask(taskIDArr[i], true);
			deletedTasks.add(tempTask); 
			taskPositions.add(tempTask.getOldPosition());
		}
		if (!undoAction){
			listener.undoableEditHappened(new UndoableEditEvent(this, new UndoableToggleEdit (COMMAND_TYPE.muldel, null, this, -1, "", "", "", "", "", "", null, taskIDArr, deletedTasks, taskPositions)));
		}
		currentStorage.updateFile();
	}
}
